#include "gmp.h"
#include "predicates.h"

point::point(double x_, double y_)
{
	x = x_;
	y = y_;
}

point::point()
{
	x = 0;
	y = 0;
}

bool point::operator < (const point &p) const
{
	return ((x < p.x) || ((x == p.x) && (y < p.y)));
}

bool point::operator == (const point &p) const
{
	return ((x == p.x) && (y == p.y));
}

bool point::operator != (const point &p) const
{
	return ((x != p.x) || (y != p.y));
}

int  left_turn_add_precision(const point &a, const point &b, const point &c)
{
        mpq_t ax, ay, bx, by, cx, cy;
        mpq_init(ax);
        mpq_init(ay);
        mpq_init(bx);
        mpq_init(by);
        mpq_init(cx);
        mpq_init(cy);
        mpq_set_d(ax, a.x);
        mpq_set_d(ay, a.y);
        mpq_set_d(bx, b.x);
        mpq_set_d(by, b.y);
        mpq_set_d(cx, c.x);
        mpq_set_d(cy, c.y);
        mpq_t tmp1, tmp2, tmp3, mul1 ,mul2;
        mpq_init(tmp1);
        mpq_init(tmp2);
        mpq_init(tmp3);
        mpq_init(mul1);
        mpq_init(mul2);
        mpq_sub(tmp1, bx, ax);                          //tmp1 = b.x - a.x
        mpq_sub(tmp2, cy, ay);                          //tmp2 = c.y - a.y
        mpq_mul(mul1, tmp1, tmp2);                      //mul1 = (b.x - a.x) * (c.y - a.y)
        mpq_sub(tmp1, by, ay);                          //tmp2 = b.y - a.y
        mpq_sub(tmp2, cx, ax);                          //tmp3 = c.x - a.x
        mpq_mul(mul2, tmp1, tmp2);                      //mul2 = (b.y - a.y) * (c.x - a.x)      
        mpq_sub(tmp3, mul1, mul2);                      //tmp3 = (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x)
        mpq_clear(tmp1);
        mpq_clear(tmp2);
        mpq_clear(mul1);
        mpq_clear(mul2);
        int ret = mpq_sgn(tmp3);
        mpq_clear(tmp3);
        return ret;
}

int left_turn(const point &a, const point &b, const point &c)
{
        double ans = (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
        if  (eps * (std::abs((b.x - a.x) * (c.y - a.y)) + std::abs((b.y - a.y) * (c.x - a.x))) < ans)
        {
                return 1;
        }
        if  (-(eps * (std::abs((b.x - a.x) * (c.y - a.y)) + std::abs((b.y - a.y) * (c.x - a.x)))) > ans)
        {
                return -1;
        }
        return left_turn_add_precision(a,b,c);
};

bool points_x_predicate(const point &a, const point &b)
{
	return a.x < b.x;
}